<?php
(!defined('IN_SYSTEM') || !defined('ADMIN_PRE')) && exit('Access Denied!');

if(!ican("sysdata")){
 msg('对不起，你没有权限执行本操作！');
}

@set_time_limit(0);
$f = isset($_REQUEST['f'])?$_REQUEST['f']:'recache';
$op=getGP('op','G');
$db_tables = array(DB_PREFIX.'article', DB_PREFIX.'orders', DB_PREFIX.'category', DB_PREFIX.'comment', DB_PREFIX.'config', DB_PREFIX.'nav', DB_PREFIX.'shops', DB_PREFIX.'notice', DB_PREFIX.'tag', DB_PREFIX.'files', DB_PREFIX.'users', DB_PREFIX.'usergroups');

if ( $f == 'recache') {
	if ( $op == 'recache' ) {
		recache();
		msg('成功刷新缓存。');
	} elseif ( $op == 'clearcachepage') {
		remove_dir(CACHE_ROOT.'./pages');
		remove_dir(CACHE_ROOT.'./templates');
		msg('成功删除所有缓存页面。');
	}
} elseif ( $f == 'recalendar' && $op == 'exec' ) {
	$_G['db']->query("TRUNCATE TABLE ".DB_PREFIX."calendar");
	$sql = "SELECT aid,dateline FROM ".DB_PREFIX."article ORDER BY dateline ASC";
	$query = $_G['db']->query($sql);
	while ($row = $_G['db']->fetch_array($query)) {
		$yearmonth = gdate('Ym',$row['dateline']);
		$day = gdate('j',$row['dateline']);
		$aid = $row['aid'];
		$_G['db']->query("INSERT INTO ".DB_PREFIX."calendar (yearmonth,day,aid) VALUES ($yearmonth,$day,$aid)");
	}
	msg('成功重建日历。');
} elseif ( $f == 'dbop' ) {
	$db_op = array('check' => '检查表', 'analyze' => '分析表', 'repair' => '修复表', 'optimize' => '优化表');
	if ( check_submit('dosubmit') ) {
		$tables = getGP('table','P','array');
		$ops = getGP('op','P','array');
		foreach ($ops as $op) {
			foreach ($tables as $table) {
				$_G['db']->query($op.' TABLE '.$table);
			}
		}
		msg('成功完成数据表维护。', '?m=data');
	}
} elseif ( $f == 'bakout' ) {
	if ( getGP('dosubmit') == 'yes' ) {
		$bakdir=getGP('bakdir');
		$baktype=getGP('baktype');
		$baktablestr=getGP('baktablestr');
		$sizelimit=getGP('sizelimit');
		$step=getGP('step');
		$tableid=getGP('tableid');
		$start=getGP('start');
		$filepre=getGP('filepre');
		
		if ( !$baktablestr ) {
			$baktables = getGP('baktables','GP','array');
			$baktablestr = implode('|', $baktables);
		} else {
			$baktables = explode('|', $baktablestr);
		}
		empty($baktables) && msg('请选中要备份的数据表。');
		$baktype != 1 && $baktype = 2;
		$sizelimit = intval($sizelimit) ? intval($sizelimit) : 2048;
		!$step && $step = 0;
		!$tableid && $tableid = 0;
		!$start && $start = 0;
		if ( empty($bakdir) ) {
			$bakdir = gdate('ymd').'_'.substr(md5(random(10).TIMESTAMP),-8);
			make_dir(DATA_DIR.'backup/'.$bakdir);
		}
		$_G['db']->query('SET SQL_QUOTE_SHOW_CREATE=0');
		$bakcontent = "# ".$_G['settings']['sitename']." Backup File\n".
				   "# Volume: $step\n".
				   "# Time: ".gdate('Y-m-d H:i', TIMESTAMP)."\n".
			       "# URL: ".$_G['settings']['siteurl']."\n".
				   "#--------------------------------------\n\n";
		if ( !$step ) {
			$filepre = 'bak_'.substr(md5(random(10).TIMESTAMP),0,8);
			$bakcontent .= baktable();
		} else {
			$bakcontent .= bakdata();
		}
		$bakfile = DATA_DIR.'backup/'.$bakdir.'/'.$filepre.'_'.$step.'.sql';
		file_put_contents($bakfile, $bakcontent);
		$step++;
		$jumpurl = "admin.php?m=data&f=bakout&dosubmit=yes&bakdir={$bakdir}&sizelimit={$sizelimit}&step={$step}&baktablestr={$baktablestr}&tableid={$tableid}&start={$start}&filepre={$filepre}";
		if ( $tableid >= count($baktables) ) {
			bakmsg("所有数据备份完成，共计<b>{$step}</b>卷，本次备份目录：".DATA_DIR."backup/$bakdir/");
		} else {
			bakmsg("分卷<b>".($step-1)."</b>备份完成，文件名为 {$filepre}_".($step-1).".sql，正在进行下一分卷备份...", $jumpurl);
		}

	} else {
		make_dir(DATA_DIR.'backup');
		$query = $_G['db']->query("SHOW TABLE STATUS");
		$prelen = strlen(DB_PREFIX);
		$sys_tb = $other_tb = array();
		while ( $row = $_G['db']->fetch_array($query) ) {
			$aname = substr($row['Name'],0,$prelen) == DB_PREFIX ? 'sys_tb' : 'other_tb';
			${$aname}[] = array(
			'name' => $row['Name'],
			'rows' => $row['Rows'],
			'size' => sizecount($row['Data_length'] + $row['Index_length'])
			);
		}
	}
} elseif ( $f == 'baklist' ) {
	$result = array();
	$bakdir = DATA_DIR.'backup';
	if ( !is_dir(DATA_DIR.'backup') ) {
		make_dir(DATA_DIR.'backup');
	}
	$dir = dir($bakdir);
	while ( false !== ($entry = $dir->read())) {
		if ( $entry != '.' && $entry != '..' ) {
			$path = $bakdir.'/'.$entry;
			if ( is_dir($path) ) {
				$bak = dir($path);
				while ( false !== ($file = $bak->read()) ) {
					if ( eregi("^bak_(.*)_0.sql$", $file) ) {
						$fp = fopen($path.'/'.$file,'rb');
						$bakinfo = fread($fp, 120);
						fclose($fp);
						$bakinfo = explode("\n", $bakinfo);
						$result[] = array(
						'dir' => $entry,
						'version' => substr($bakinfo[1],17),
						'time' => substr($bakinfo[2],8)
						);
						break;
					}
				}
				$bak->close();
			}
		}
	}
	$dir->close();
} elseif ( $f == 'bakin' ) {
	$bakdir=getGP('bakdir');
	$dosubmit=getGP('dosubmit');
	if ( !eregi('^[0-9a-z_]+$', $bakdir) ) {
		msg("备份目录<b>$bakdir</b>不合法。");
	}
	if ( $dosubmit == 'yes' ) {
		$volume=getGP('volume');
		$filepre=getGP('filepre');
		$count=getGP('count');
		!$volume && $volume = 1; //不导入表结构文件
		$bakfile = DATA_DIR."backup/{$bakdir}/bak_{$filepre}_{$volume}.sql";
		if ( $volume >= $count ) {
			bakmsg("所有数据还原完成，共计 <b>".($volume-1)."</b> 卷，卷号为 <b>0</b> 的文件为数据表结构文件，不被导入。");
		} elseif ( file_exists($bakfile) ) {
			bakindata($bakfile);
			$volume ++;
			$jumpurl = "admin.php?m=data&f=bakin&dosubmit=yes&bakdir={$bakdir}&volume={$volume}&filepre={$filepre}&count={$count}";
			bakmsg("分卷<b>".($volume-1)."</b>导入完成，正在导入下一分卷...", $jumpurl);
		}
	} else {
		$result = array('count'=>0,'dir'=>DATA_DIR.'backup/'.$bakdir.'/');
		$path = DATA_DIR.'backup/'.$bakdir;
		$dir = dir($path);
		while ( false !== ( $file = $dir->read()) ) {
			if ( preg_match('/^bak_(.*)_([0-9]+).sql$/i', $file, $matches) ) {
				if ( $matches[2] == 0 ) {
					$fp = fopen($path.'/'.$file,'rb');
					$bakinfo = fread($fp, 200);
					fclose($fp);
					$bakinfo = explode("\n", $bakinfo);
					$result['filepre'] = $matches[1];
					$result['time'] = substr($bakinfo[2],8);
					$result['count'] ++;
				} else {
					$result['count'] ++;
				}
			}
		}
		$dir->close();
	}
} elseif ( $f == 'bakdel' ) {
	$bakarr = getGP('id','P','array');
	if ( empty($bakarr) ) msg('请选中要删除的目录。'); 
	foreach ( $bakarr as $val ) {
		if ( strpos($val, '..') === false ) {
			if ( is_dir(DATA_DIR.'backup/'.$val) ) {
				remove_dir(DATA_DIR.'backup/'.$val);
			}
		}
	}
	msg('成功删除选中的目录。', 'admin.php?m=data&f=baklist');
} elseif ( $f == 'rebuildurl'  && $op == 'exec') {
	$cates = $_G['db']->fetch_all("SELECT cid,urlname FROM".table('category')."WHERE urlname!=''");
	$articles = $_G['db']->fetch_all("SELECT aid,urlname FROM".table('article')."WHERE urlname!=''");
	$pages = $_G['db']->fetch_all("SELECT id,urlname FROM".table('page')."WHERE urlname!=''");
	
	if(!empty($cates)){
		foreach($cates as $cv){
			$urlalias['category'][$cv['cid']]=$cv['urlname'];
		}
	}
	if(!empty($articles)){
		foreach($articles as $av){
			$urlalias['article'][$av['aid']]=$av['urlname'];
		}
	}
	if(!empty($pages)){
		foreach($pages as $pv){
			$urlalias['page'][$pv['id']]=$pv['urlname'];
		}
	}
	
	$val = my_serialize($urlalias);
	
	if ($_G['db']->fetch_one_array("SELECT * FROM ".DB_PREFIX."settings WHERE `type` = '' AND `name` = 'alias'")) {
		$_G['db']->query("UPDATE ".DB_PREFIX."settings SET `value` = '$val' WHERE `type` = '' AND `name` = 'alias'");
	} else {
		$_G['db']->query("INSERT INTO ".DB_PREFIX."settings (`name`, `value`, `type`) VALUES ('alias', '$val', '')");
	}
	recache('settings');
	msg('成功重建别名。');
}
function baktable() {
	global $_G,$baktables;
	$sql = '';
	foreach ( $baktables as $table ) {
		$row = $_G['db']->fetch_one_array("SHOW CREATE TABLE $table");
		$sql .= "DROP TABLE IF EXISTS $table;\n\n";
		$sql .= $row['Create Table'].";\n\n";
	}
	return $sql;
}
function bakdata() {
	global $_G,$baktables,$tableid,$sizelimit,$start;
	$count = count($baktables);
	$baksql = '';
	for ( $i=$tableid; $i<$count; $i++ ) {
		$tableid = $i;
		$stop = $finish = false;
		if ( $start == 0 ) {
			$baksql .= "TRUNCATE TABLE $baktables[$i];\n";
		}
		$status = $_G['db']->fetch_one_array("SHOW TABLE STATUS LIKE '$baktables[$i]'");
		$rows = $status['Rows'];
		while ( !$stop ) {
			$query = $_G['db']->query("SELECT * FROM `".$baktables[$i]."` LIMIT $start, 5000");
			$fields = $_G['db']->num_fields($query);
			while ( $row = $_G['db']->fetch_array($query,MYSQL_NUM) ) {
				$start ++;
				$baksql .= "INSERT INTO $baktables[$i] VALUES ('".mysql_escape_string($row[0])."'";
				for ( $j=1; $j<$fields; $j++) {
					$baksql .= " ,'".mysql_escape_string($row[$j])."'";
				}
				$baksql .= ");\n";
				if ( strlen($baksql) > ($sizelimit * 1000) ) {
					$stop = true;
					break;
				}
			}
			$_G['db']->free_result($query);
			if ( $start >= $rows ) {
				$stop = true;
				$finish = true;
				$start = 0;
			}
		}
		if ( strlen($baksql) > ($sizelimit * 1000) ) {
			break;
		}
		if ( $finish && $tableid == $count - 1 ) $tableid ++;
	}
	return $baksql;
}
function bakindata($file) {
	global $_G;
	$baksql = file($file);
	foreach ($baksql as $key => $val) {
		$val = trim($val);
		if (!$val || substr($val,0,1) == '#') continue;
		if ( eregi('\;$', $val) ) {
			$query .= $val;
			if ( eregi('^CREATE',$query) ) {
				$query = substr($query, 0, strrpos($query, ')')+1);
				if( $_G['db']->version() > '4.1' ){
					$query .= 'ENGINE=MyISAM DEFAULT CHARSET=utf8;';
				} else {
					$query .= 'TYPE=MyISAM;';
				}
			} elseif ( eregi('^INSERT', $query) ) {
				$query = 'REPLACE '.substr($query,6);
			}
			$_G['db']->query($query);
			$query = '';
		} else {
			$query .= $val;
		}
	}
	
}
function bakmsg($message, $url = null) {
	$jump = '';
	if ( $url ) {
		$jump = '<script type="text/javascript">setTimeout("window.location.href=\''.$url.'\'",500);</script>';
	}
	echo <<<EOT
	<html>
	<head></head>
	<body>
	<p>{$message}</p>
	{$jump}
	</body>
	</html>
EOT;
	exit;
}
include admintemplate('data');
?>